/*
 *  logic.cpp
 *  
 *  Created by James Dykstra
 *	Team 5
 *
 *  Copyright 2010 Michigan Technological University. All rights reserved.
 */
#include "logic.h"
#include "sprite.h"

Logic::Logic(Renderer *rnd, Map* m)
{
	renderer = rnd;
	map = m;
}
Logic::~Logic()
{
}
bool Logic::checkCollide(Sprite *spr1, Sprite *spr2)
{
	if(spr1!=0 && spr2!=0 && spr1->getHitbox()!=0 && spr2->getHitbox()!=0)
	{
		float dist = sqrt((spr1->getRect()->x-spr2->getRect()->x) + (spr1->getRect()->y-spr2->getRect()->y));
		if(dist < (spr1->getRadius()+spr2->getRadius()));
		{
		Hitbox *A = spr1->getHitbox();
		Hitbox *B = spr2->getHitbox();
		
		A->calcWorldCoords((spr1->getRect()->x), (spr1->getRect()->y), spr1->getAngle());
		B->calcWorldCoords((spr2->getRect()->x), (spr2->getRect()->y), spr2->getAngle());

		   
		Hitbox *list[3];
		list[0] = A;
		list[1] = B;
		list[2] = A;
		
		Vector *p;
		Vector *tmp;
		   
		float t1;
		float t2;
		float min;
		float max;
		   
		for(int i = 0;i < 2;i++)
		{
		       for(int a = 0;a < 2;a++)
		       {
			 p = new Vector(list[i]->getWorldCoord(a+1)->getX() - list[i]->getWorldCoord(a)->getX(), list[i]->getWorldCoord(a+1)->getY() - list[i]->getWorldCoord(a)->getY());
			 p->normalize();
		      
			 tmp = list[i]->getWorldCoord(a)->projectVector(p);
			 t1 = tmp->magnitude();
			 delete tmp;
			
			 tmp = list[i]->getWorldCoord(a+1)->projectVector(p);
			 t2 = tmp->magnitude();
			 delete tmp;
			       
			 min = minimum(t1, t2);
			 max = maximum(t1, t2);
		      
			 float proj[4];
		      
			 for(int b = 0;b < 4;b++)
			 {
			    tmp = list[i+1]->getWorldCoord(b)->projectVector(p);
			    proj[b] = tmp->magnitude();
			    delete tmp;
			 }
		      
			 if(!umbrellas(min, max, proj))
			{
		  	    A->clearWorldCoords();
			    B->clearWorldCoords();
			    return false;
			}
		   }
		}
		A->clearWorldCoords();
		B->clearWorldCoords();
		printf("Collision between %s and %s\n", A->getIdentifier(), B->getIdentifier());
      
		return true;
		}
		return false;
	}
	else
		return false;
}

bool Logic::validMove(Sprite * sprite, int xOffset, int yOffset, float angle)
{
	bool returnValue = true;
	sprite->getRect()->x += xOffset;
	sprite->getRect()->y += yOffset;
	sprite->setAngle((sprite->getAngle()+angle));
	do {
		if(((sprite->getRect()->x + sprite->getRect()->w) > map->getMapWidth()) || (sprite->getRect()->x < 0)) {
			returnValue=false;
			break;
		}
		
		if(((sprite->getRect()->y + sprite->getRect()->h) > map->getMapHeight()) || (sprite->getRect()->y < 0)) {
			returnValue=false;
			break;
		}
		
		for (int i=0; i<map->getNumObstacles(); i++) {
			if (checkCollide(sprite, map->getObstacle(i))) {
				returnValue = false;
				break;
			}
		}
	} while (false);
	
	sprite->getRect()->x -= xOffset;
	sprite->getRect()->y -= yOffset;
	sprite->setAngle((sprite->getAngle()-angle));
	
	return returnValue;
}
float Logic::minimum(float a, float b)
{
	if(a < b)
		return a;
	else
		return b;
}
float Logic::maximum(float a, float b)
{
	if(a > b)
		return a;
	else
		return b;
}

bool Logic::umbrellas(float min, float max, float proj[])
{
   bool less = false;
   bool more = false;
   
   //printf("%2.2f , %2.2f\n", min, max);
   
   for(int loop = 0;loop < 4;loop++)
   {
      if(proj[loop] >= min && proj[loop] <= max)
         return true;
      else if(proj[loop] < min)
         less = true;
      else if(proj[loop] > max)
         more = true;
   }
   
   if(less && more)
      return true;
   
   return false;
}
